package logic

import (
	"context"
	"time"

	"github.com/golang-jwt/jwt/v4"
	"github.com/iriver/ai-offer/backend/internal/model"
	"github.com/iriver/ai-offer/backend/internal/svc"
	"github.com/iriver/ai-offer/backend/internal/types"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/rest/httpx"
)

type LoginLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginLogic {
	return &LoginLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *LoginLogic) Login(req *types.LoginRequest) (resp *types.TokenResponse, err error) {
	// 查找用户
	user, err := l.svcCtx.UserStore.FindByEmail(req.Email)
	if err != nil {
		if err == model.ErrNotFound {
			l.Logger.Infof("用户不存在: %s", req.Email)
			return nil, httpx.NewCodeError(types.ErrUserNotFound, "用户不存在")
		}
		l.Logger.Errorf("查询用户失败: %v", err)
		return nil, httpx.NewCodeError(types.ErrDatabase, "登录失败，请稍后重试")
	}

	// 验证密码
	if !model.ComparePassword(user.PasswordHash, req.Password) {
		l.Logger.Infof("密码错误: %s", req.Email)
		return nil, httpx.NewCodeError(types.ErrInvalidPassword, "用户名或密码错误")
	}

	// 生成访问令牌
	accessToken, err := l.generateAccessToken(user)
	if err != nil {
		l.Logger.Errorf("生成访问令牌失败: %v", err)
		return nil, httpx.NewCodeError(types.ErrTokenGeneration, "登录失败，请稍后重试")
	}

	// 生成刷新令牌
	refreshToken, err := l.generateRefreshToken(user)
	if err != nil {
		l.Logger.Errorf("生成刷新令牌失败: %v", err)
		return nil, httpx.NewCodeError(types.ErrTokenGeneration, "登录失败，请稍后重试")
	}

	// 返回令牌
	resp = &types.TokenResponse{
		AccessToken:  accessToken,
		RefreshToken: refreshToken,
		ExpiresAt:    time.Now().Unix() + l.svcCtx.Config.Auth.AccessExpire,
		TokenType:    "Bearer",
	}

	l.Logger.Infof("用户登录成功: %s", req.Email)
	return resp, nil
}

// 生成JWT访问令牌
func (l *LoginLogic) generateAccessToken(user *model.UserModel) (string, error) {
	now := time.Now().Unix()
	claims := make(jwt.MapClaims)
	claims["exp"] = now + l.svcCtx.Config.Auth.AccessExpire
	claims["iat"] = now
	claims["userId"] = user.ID
	claims["email"] = user.Email
	claims["role"] = user.Role
	token := jwt.New(jwt.SigningMethodHS256)
	token.Claims = claims
	return token.SignedString([]byte(l.svcCtx.Config.Auth.AccessSecret))
}

// 生成JWT刷新令牌
func (l *LoginLogic) generateRefreshToken(user *model.UserModel) (string, error) {
	now := time.Now().Unix()
	claims := make(jwt.MapClaims)
	claims["exp"] = now + l.svcCtx.Config.Auth.RefreshExpire
	claims["iat"] = now
	claims["userId"] = user.ID
	token := jwt.New(jwt.SigningMethodHS256)
	token.Claims = claims
	return token.SignedString([]byte(l.svcCtx.Config.Auth.RefreshSecret))
}
